package com.powerunion.datacollection.report.excelreport.config;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import jxl.Workbook;

import org.dom4j.Element;

import com.powerunion.datacollection.report.excelreport.Logger;
import com.powerunion.datacollection.report.excelreport.util.HelpTools;

/**
 * 该类负解析和保存报表的配置信息。
 * @author juny
 */
public class ReportConfig { 
    private static Logger log = Logger.getLogger(ReportConfig.class);
    public ReportConfig(ReportConfigManager config){
        this.config = config;
        sheets = new HashMap();
    }
    
    /**
     * 解析一个report信息定义节点，并将解析后的信息保存。
     * @param node
     * @return
     */
    public boolean bindReport(Element node){
        reportName = node.attributeValue("name");
        templetfile = node.attributeValue("templetfile");
        cacheTempletFile = node.attributeValue("cachefile");
        if(!HelpTools.notEmpty(cacheTempletFile)){
            cacheTempletFile = "";
        }
        
        String size = node.attributeValue("initReportBufSize");
        if(HelpTools.notEmpty(size)){
            this.initialFileSize = HelpTools.parseInt(size, 1024*1024);
        }
        
        size = node.attributeValue("bufGrowSize");
        if(HelpTools.notEmpty(size)){
            this.growSize = HelpTools.parseInt(size, 512*1024);
        }
        
        Iterator notes = node.elementIterator();
        Element subNode = null;
        SheetConfig sheet = null;
        String sheetName = "";
        while (notes.hasNext()) {
            subNode = (Element) notes.next();
            if (subNode.getName().equals(NOTE_SHEET)) {
                sheetName = subNode.attributeValue("name");
                sheet = new SheetConfig();
                sheet.bindSheet(subNode);
                sheets.put(sheetName, sheet);
            }else if(subNode.getName().equals(NOTE_EMBEDDEDOBJECT)){
                embeddedObjectClass = subNode.attributeValue("class");
                embeddedObjectName = subNode.attributeValue("name");
            }
        }
        
        return true;
    }
    
    /**
     * 取得当前报表配置对象中sheet节点配置信息。
     * @param sheetName	要取得信息的sheet名称
     * @return
     */
    public SheetConfig getSheet(String sheetName){
        return (SheetConfig)sheets.get(sheetName);
    }
    
    /**
     * 取得当前报表所定义的sheet名称列表。
     * @return
     */
    public String[] getSheetName(){
        return (String[])sheets.keySet().toArray(new String[sheets.size()]);
    }
    
    /**
     * 取得当前报表定义的嵌入对象类名。
     * @return
     */
    public String getEmbeddedObject(){
        return this.embeddedObjectClass;
    }
    
    /**
     * 获得创建报表文件时预分配文件缓存区大小。默认是分配1M
     * @return
     */
    public int getInitialFileSize(){
        return this.initialFileSize;
    }
    
    /**
     * 获取当缓存不够时，每次增长文件缓存区空间大小。默认是512K
     * @return
     */
    public int getGrowSize(){
        return this.growSize;
    }
    
    public String toString(){
        StringBuffer ret = new StringBuffer();
        ret.append(" report:" + reportName + " templet file:" + templetfile);
        ret.append("\n");
        ret.append(sheets.toString());
        return ret.toString();
    }
    
    /**
     * 取得当前报表对象定义的模板信息。
     * @return
     * @throws Exception
     */
    public synchronized Workbook getTempletWorkbook() throws Exception{
        if(null == templetFileBuffer){
            //装载模板文件到内存中。
            String path = config.getTempletFilePath() + 
									  File.separator + 
									  templetfile;
            templetFileBuffer = new BufferedInputStream(
				                    	new FileInputStream(
				                            	new File(path)
				                        )
				                    );
            int size = templetFileBuffer.available();
	        templetFileBuffer.mark(size + 1);
	        //book = Workbook.getWorkbook(templetFileBuffer);
        }
        
        templetFileBuffer.reset();
        Workbook wb = Workbook.getWorkbook(templetFileBuffer);
        //如果不cache，则释放已经打开的资源
        if(cacheTempletFile.equalsIgnoreCase(NOT_CACHE_TEMPLET_FILE)){
            templetFileBuffer.close();
            templetFileBuffer = null;
        }
        
        return wb;
        
        //return book;
    }
    //private Workbook book = null;
    private String cacheTempletFile;
    private String reportName = "";
    private String templetfile = "";
    private Map sheets = null;
    private ReportConfigManager config = null;
    private BufferedInputStream templetFileBuffer = null;
    private String embeddedObjectClass = null;
    private String embeddedObjectName = null;
    private int initialFileSize = 1024 * 1024; //默认创建缓冲文件大小为1M
    private int growSize = 512 * 1024; //默认文件增长大小为512K
    
    private static final String NOTE_TEMPLET_FILE = "templetfile";
    private static final String NOTE_DATA_SOURCE = "datasource";
    private static final String NOTE_SHEET = "sheet";
    private static final String NOTE_EMBEDDEDOBJECT = "embeddedObject";
    public static final String REPORT_STYLE_NORMAL = "normal";
    public static final String REPORT_STYLE_CARD = "card";
    public static final String REPORT_STYLE_LIST = "list";
    
    private final static String NOTE_DATASOURCE = "datasource";
    private final static String NOTE_BAND = "band";
    private final static String NOTE_GROUP = "group";
    private final static String NOTE_PARAMETER_INIT = "param-init";
    
    public static final String REPORT = "report";
    private final static String NOT_CACHE_TEMPLET_FILE = "false";
    
    public class SheetConfig{
        public int index = 0;
        public String name = "";
        
        public SheetConfig(){
            sources = new HashMap();
            bandGroups = new HashMap();
        }
        
        public DataSourceConfig getDataSource(String sourceName){
            return (DataSourceConfig)sources.get(sourceName);
        }
        
        public GroupConfig getGroupConfig(String groupName){
            return (GroupConfig)this.bandGroups.get("G"+groupName);
        }
        
        public BandConfig getBandConfig(String bandName){
            return (BandConfig)this.bandGroups.get("B"+bandName);
        }
        
        public boolean bindSheet(Element node){
            name = node.attributeValue("name");
            index = Integer.parseInt(node.attributeValue("index"));
            reportStyle = node.attributeValue("reportstyle");
            
            Iterator notes = node.elementIterator();
            Element subNode = null;
            DataSourceConfig source = null;
            String dataSource = "";
            String sourceName = "";
            while (notes.hasNext()){
                subNode = (Element)notes.next();
                if(subNode.getName().equals(NOTE_DATASOURCE)){
	                dataSource = subNode.attributeValue("source");
	                sourceName = subNode.attributeValue("name");
	                source = config.getDataSource(dataSource);
	                sources.put(sourceName, source);
	                //绑定该数据源初始化参数配置信息
	                if(subNode.elementIterator().hasNext()){
	                    bindIniParams(subNode, sourceName);
	                }
                }else if(subNode.getName().equals(NOTE_BAND)){
                    String name = subNode.attributeValue("name");
                    BandConfig band = new BandConfig();
                    band.bind(subNode);
                    bandGroups.put("B"+name, band);
                }else if(subNode.getName().equals(NOTE_GROUP)){
                    String name = subNode.attributeValue("name");
                    GroupConfig group = new GroupConfig();
                    group.bind(subNode);
                    bandGroups.put("G"+name, group);
                }
            }
            return true;
        }
        
        //解析数据源配置的初始化参数的配置信息。
        public void bindIniParams(Element node, String sourceName){
            if(null == sourceIniParam){
                sourceIniParam = new HashMap();
            }
            
            Iterator nodes = node.elementIterator();
            Element subNode = null;
            Map params = new HashMap();
            String name = null, value = null;
            while (nodes.hasNext()){
                subNode = (Element)nodes.next();
                if(subNode.getName().equals(NOTE_PARAMETER_INIT)){
                    name = subNode.attributeValue("name");
                    value = subNode.attributeValue("value");
                    params.put(name, value);
                }
            }
            //保存该数据源的初始化参数配置信息
            sourceIniParam.put(sourceName, params);
        }
        
        public String toString(){
            StringBuffer ret = new StringBuffer();
            ret.append(" sheetname=" + name + " index=" + index + " reportStyle=" + reportStyle);
            ret.append("\n");
            //for(int i=0; i<sources.size(); i++){
                ret.append(sources.toString());
            //}
            ret.append("\n");
            return ret.toString();
        }
        
        public Object[] getDataSourceNames(){
            return sources.keySet().toArray();
        }
        
        public Map getDataSourceParamInit(String dsName){
            if(null != sourceIniParam){
                return (Map)sourceIniParam.get(dsName);
            }else{
                return null;
            }
        }
        
        public String getReportStyle(){
            return reportStyle;
        }
        
        private Map sources = null;			//报表数据源配置信息。
        private Map sourceIniParam = null; 	//保存配置的初始化参数信息
        private Map bandGroups = null;  			//band配置信息
        private String reportStyle = "";	//报表风格
    }
    
    public class BandConfig{
        public boolean bind(Element node){
            name = node.attributeValue("name");
            return true;
        }
        
        public String getName(){
            return name == null ? "" : name;
        }
        private String name = null;
        
    }
    
    public class GroupConfig{
        public boolean bind(Element node){
            name = node.attributeValue("name");
            String groupBy = node.attributeValue("groupby");
            if(null != groupBy && !"".equals(groupBy)){
                iniGroupByFields(groupBy);
            }
            dsName = node.attributeValue("dataSource");
            return true;
        }
        
        public String getName(){
            return name == null ? "" : name;
        }
        
        public String getDsName(){
            return dsName == null ? "" : dsName;
        }
        
        public String[] getGroupByFields(){
            return this.groupby;
        }
        
        private void iniGroupByFields(String groupby){
            this.groupby = groupby.split(",");
        }
        private String dsName = null;
        private String name = null;
        private String[] groupby = null;
    }
}
